﻿using System;
using System.Text;
using System.Runtime.InteropServices;

namespace Printer.T6000
{
    class PrintRaw
    {
        private string cmdbuf;
        private string head;
        private string end;

        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
        public class DOCINFOA
        {
            [MarshalAs(UnmanagedType.LPStr)]
            public string pDocName;
            [MarshalAs(UnmanagedType.LPStr)]
            public string pOutputFile;
            [MarshalAs(UnmanagedType.LPStr)]
            public string pDataType;
        }

        [DllImport("winspool.Drv", EntryPoint = "OpenPrinterA")]
        static extern bool OpenPrinter([MarshalAs(UnmanagedType.LPStr)] string szPrinter, out IntPtr hPrinter, IntPtr pd);

        [DllImport("winspool.Drv", EntryPoint = "ClosePrinter")]
        public static extern bool ClosePrinter(IntPtr hPrinter);

        [DllImport("winspool.Drv", EntryPoint = "StartDocPrinterA")]
        static extern bool StartDocPrinter(IntPtr hPrinter, Int32 level, [In, MarshalAs(UnmanagedType.LPStruct)] DOCINFOA di);

        [DllImport("winspool.Drv", EntryPoint = "EndDocPrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
        public static extern bool EndDocPrinter(IntPtr hPrinter);
 
        [DllImport("winspool.Drv", EntryPoint = "StartPagePrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
        public static extern bool StartPagePrinter(IntPtr hPrinter);
 
        [DllImport("winspool.Drv", EntryPoint = "EndPagePrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
        public static extern bool EndPagePrinter(IntPtr hPrinter);
 
        [DllImport("winspool.Drv", EntryPoint = "WritePrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
        public static extern bool WritePrinter(IntPtr hPrinter, IntPtr pBytes, Int32 dwCount, out Int32 dwWritten);

        [DllImport("winspool.Drv", EntryPoint = "GetDefaultPrinterA")]
        public static extern bool GetDefaultPrinter(IntPtr pName, out Int32 dwWritten);

        public PrintRaw()
        {
            head = "!PTX_SETUP\r\n" +
                  "ENGINE-WIDTH;2020:LENGTH;5907:MIRROR;0.\r\n" +
                  "PTX_END\r\n" +
                  "~CREATE;FORM-0;425\r\n" +
                  "SCALE;DOT;203;203\r\n" +
                  "ISET;'UTF8'\r\n" +
                  "FONT;NAME RSCUHEIR.ttf\r\n";

            cmdbuf = null;
 
            end = "END\r\n" +
                 "~PAPER;CUT 1;PAUSE 0;TEAR 0\r\n" +
                 "~EXECUTE;FORM-0;1\r\n" +
                 "~NORMAL\r\n" +
                 "~DELETE FORM;FORM-0\r\n";

        }
 
        static byte[] toutf8(string str)
        {
            byte[] u, g;
            Encoding gb, utf;

            gb = Encoding.GetEncoding("gb2312");
            utf = Encoding.GetEncoding("utf-8");

            g = gb.GetBytes(str);
            u = Encoding.Convert(gb, utf, g);
 
            return u;
        }

        public void AddText(int x, int y, int fs, string str, int bold = 0)
        {
            string l2;
            string buf = "ALPHA\r\n";

            l2 = string.Format("INV;POINT;{0:D};{1:D};{2:D};{3:D};\"{4:G}\"\r\n",
                               x, y, fs, fs, str);

            buf += l2;
            buf += "STOP\r\n";
 
            cmdbuf += buf;
        }

        public void AddQrCode(int x, int y, int fs, string str)
        {
            string buf;
            string l2;
      
            buf = "BARCODE\r\n";
            l2 = string.Format("QRCODE;INV;XD{0:D};T2;E0;M0;I0;{1:D};{2:D}\r\n", fs, x, y);
            l2 += string.Format("\"{0:G}\"\r\n", str);
            buf += l2;
            buf += "STOP\r\n";

            cmdbuf += buf;
        }

        public byte[] GetRaw()
        {
            return toutf8(head + cmdbuf + end);
        }
 
        public bool WriteRaw(string printername, byte[] raw)
        {
            Int32 dwWritten = 0;
            IntPtr hPrinter = new IntPtr(0);
            DOCINFOA di = new DOCINFOA();
            bool bSuccess = false;
            IntPtr buffer;

            di.pDocName = "T6000-PF";
            di.pDataType = "RAW";
            di.pOutputFile = null;
 
            if (printername.Length == 0)
                printername = DefaultPrinter();
 
            if (!OpenPrinter(printername.Normalize(), out hPrinter, IntPtr.Zero))
                return false;

            buffer = Marshal.AllocHGlobal(raw.Length);
            if (StartDocPrinter(hPrinter, 1, di))
            {
                if (StartPagePrinter(hPrinter))
                {
                    Marshal.Copy(raw, 0, buffer, raw.Length);
                    bSuccess = WritePrinter(hPrinter, buffer, raw.Length, out dwWritten);
                    EndPagePrinter(hPrinter);
                }
                EndDocPrinter(hPrinter);
            }
            ClosePrinter(hPrinter);
            Marshal.FreeHGlobal(buffer);
   
            return bSuccess;
        }

        public string DefaultPrinter()
        {
            string name = "";
            Int32 size = 0;

            GetDefaultPrinter(IntPtr.Zero, out size);
            if (size != 0)
            {
                IntPtr pn;

                pn = Marshal.AllocHGlobal(size + 1);
                GetDefaultPrinter(pn, out size);
                name = Marshal.PtrToStringAnsi(pn);
                Marshal.FreeHGlobal(pn);
            }
        
            return name;
        }
 
        public bool Print(string printername = "")
        {
            bool ret;
            byte[] raw;
            
            raw = GetRaw();
            ret = WriteRaw(printername, raw);
            cmdbuf = null;
 
            return ret;
        }

        public bool PrintTest()
        {
            string qr = 
            "0000000000000000000000;\r\n" +
            "C1F/云烟85/会理县测试烟点\r\n" +
            "定级:测试测试\r\n" +
            "仓管:测试测试\r\n" +
            "烟农:测试测试";

            AddText(830, 400, 10, "产地: 测试 测试烟点");
            AddText(790, 320, 10, "*号收购线");
            AddText(750, 370, 10, "红花大金元 测试");
            AddText(670, 320, 32, "C1F");
            AddText(630, 400, 10, "成件管理: 测试测试");
            AddText(590, 400, 10, "仓管: 测试测试");
            AddText(550, 400, 10, "质管: 测试测试");
            AddText(510, 400, 10, "定级: 测试测试");
            AddText(470, 400, 10, "司磅: 测试测试");
            AddText(430, 400, 10, "烟农: 测试测试");
            AddText(390, 400, 10, "净重: 44.44kg");
            AddText(350, 400, 10, "成件时间: 20131111 12:11");

            AddQrCode(110, 120, 4, qr);
        
            AddText(80, 400, 10, "0000000000000000000000");
            AddText(40, 200, 10, "打印次数: 2");

            return Print();
        }
    }
}
